#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <modbus.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/shm.h>

// 主机
pthread_t tid, tid1;
modbus_t *mod;
uint16_t arr[64] = {0};
int a, b;
uint16_t *p;
uint8_t *q;

void *handler_data(void *arg) // 读保持传感器函数
{
    // 创建共享内存和服务器通信
    //   1,创建独一无二的key
    key_t key = ftok("./mudbus-project_c.c", 'a');
    if (key < 0)
    {
        perror("ftok err");
        return -1;
    }
    // 2.创建或者打开共享内存 shmget
    int shmid = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid < 0)
    {
        if (errno == EEXIST)
        {
            shmid = shmget(key, 256, 0666);
        }
        else
        {
            perror("shmget err");
            return -1;
        }
    }
    // 3.映射共享内存到实际的物理地址（用户空间）shmat
    p = (uint16_t *)shmat(shmid, NULL, 0);
    if (p == (char *)-1)
    {
        perror("shmat err");
        return -1;
    }

    while (1)
    {
        modbus_read_registers(mod, 0, 4, arr);
        // 向共享内存写入数据
        for (int i = 0; i < 4; i++)
        {
            p[i]=arr[i];
        }
        sleep(1);
    }
}

void *handler_ctl(void *arg) // 写多个线圈函数
{
    // 创建共享内存和服务器通信
    //   1,创建独一无二的key
    key_t key = ftok("./mudbus-project_c.c", 'b');
    if (key < 0)
    {
        perror("ftok err");
        return -1;
    }
    // 2.创建或者打开共享内存 shmget
    int shmid = shmget(key, 256, IPC_CREAT | IPC_EXCL | 0666);
    if (shmid < 0)
    {
        if (errno == EEXIST)
        {
            shmid = shmget(key, 256, 0666);
        }
        else
        {
            perror("shmget err");
            return -1;
        }
    }
    // 3.映射共享内存到实际的物理地址（用户空间）shmat
    q = (uint8_t *)shmat(shmid, NULL, 0);
    if (q == (char *)-1)
    {
        perror("shmat err");
        return -1;
    }
    while (1)
    {
        // printf("请输入命令：\n");
        // scanf("%d %d", &a, &b);
        // if (a == 0 && b == 0)
        // {
        //     arr[0] = 0;
        //     printf("led灯关闭\n");
        // }
        // else if (a == 0 && b == 1)
        // {
        //     arr[0] = 1;
        //     printf("led灯打开\n");
        // }
        // else if (a == 1 && b == 0)
        // {
        //     arr[1] = 0;
        //     printf("蜂鸣器关闭\n");
        // }
        // else if (a == 1 && b == 1)
        // {
        //     arr[1] = 1;
        //     printf("蜂鸣器打开\n");
        // }
        modbus_write_bit(mod, q[0], q[1]);
        sleep(1);
    }
}

int main(int argc, char const *argv[])
{
    // 创建实例
    mod = modbus_new_tcp("192.168.1.54", 502);
    if (NULL == mod)
    {
        perror("mod err\n");
    }
    // 设置从机id
    int modbus_slave = modbus_set_slave(mod, 1);
    // 连接
    int modbuscon = modbus_connect(mod);
    if (modbuscon < 0)
    {
        perror("connect errn");
    }
    // 数据处理
    int keep = pthread_create(&tid, NULL, handler_data, NULL); // 创建读保持寄存器器线程
    if (keep < 0)
    {
        perror("keep pthread_create err");
        return -1;
    }

    int xianquan = pthread_create(&tid1, NULL, handler_ctl, NULL); // 创建写多个线圈线程
    if (xianquan < 0)
    {
        perror("xianquan pthread_create err");
        return -1;
    }
    while (1);
    // 回收线程
    pthread_detach(tid);
    pthread_detach(tid1);
    // 关闭释放实例
    modbus_close(mod);
    modbus_free(mod);
    return 0;
}